我们刚接触android
开发的时候,应该都是从写布局开始的,在写布局的时候一般组长都要求我们少嵌套,这个是为什么呢?这个就要从我们今天要分析的invalidate()
分析。我们开始进入正题:
1 | /** |
可以看到我们最终会进入invalidateInternal
这个函数可以看到这段代码:
1 | final ViewParent p = mParent; |
很明显的就是进入了父布局的invalidateChild
函数,我们就从ViewGroup
里面看
1 | /** |
从这里我们就知道了,首先会检测线程,也就是为什么在子线程更新UI
为什么会崩溃的原因,然后经过一系列的判断进入到scheduleTraversals
函数,在这个函数中可以看到会调用mTraversalRunnable
这个Runnable
1 | final TraversalRunnable mTraversalRunnable = new TraversalRunnable(); |
可以看到,实际上就是调用了performTraversals()
函数,这个函数很长,我们主要看关键点:
1 | private void performTraversals() { |
可以看到,进入这里面了,会依次调用performMeasure
performLayout
performDraw
三个函数,依次调用了view
的绘制流程。
顾名思义,在performMeasure
中主要会实现测量
1 | private void performMeasure(int childWidthMeasureSpec, int childHeightMeasureSpec) { |
mView
就是ViewGroup
,然后会调用ViewGroup
的onMeasure
函数,然后测量,就从最上层父布局一直到测量到最底层的view
。performLayout
主要负责子view
摆放
1 | private void performLayout(WindowManager.LayoutParams lp, int desiredWindowWidth, |
同样的道理,又是从最上层viewGroup
到最底层的view
。performDraw
负责绘制,performDraw()
会 调用draw
,在调用drawSoftware
1 | /** |
从mView.draw(canvas);
可以看到,又是一样的从最上层ViewGroup
一直调用最底层view
,不断的从draw
方法调用drawBackground->onDraw->dispatchDraw->onDrawForeground
。
流程为下图:
从这更加验证了我们嵌套多层之后会消耗性能的真理。invalidate()
就分析到这里了,有什么意见或者文中有什么错误的希望可以在下方评论。希望大家可以在看我的文章中可以学习到知识。
v1.5.2